package com.javablog.controller;

import com.javablog.dto.CommentDto;
import com.javablog.dto.UserSummaryDto;
import com.javablog.dto.response.MessageResponse;
import com.javablog.dto.response.PagedResponse;
import com.javablog.model.Article;
import com.javablog.model.Comment;
import com.javablog.model.User;
import com.javablog.repository.ArticleRepository;
import com.javablog.repository.CommentRepository;
import com.javablog.repository.UserRepository;
import com.javablog.security.services.UserDetailsImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@CrossOrigin(origins = "*", maxAge = 3600)
@RestController
@RequestMapping("/api/comments")
public class CommentController {
    
    @Autowired
    private CommentRepository commentRepository;
    
    @Autowired
    private ArticleRepository articleRepository;
    
    @Autowired
    private UserRepository userRepository;
    
    @GetMapping("/article/{articleId}")
    public ResponseEntity<?> getCommentsByArticle(
            @PathVariable Long articleId,
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "10") int size) {
        
        Article article = articleRepository.findById(articleId)
                .orElseThrow(() -> new RuntimeException("错误：文章未找到。"));
        
        Pageable pageable = PageRequest.of(page, size, Sort.by(Sort.Direction.DESC, "createdAt"));
        Page<Comment> commentsPage = commentRepository.findByArticle(article, pageable);
        
        List<CommentDto> content = commentsPage.getContent().stream()
                .map(this::convertToDto)
                .collect(Collectors.toList());
        
        PagedResponse<CommentDto> response = new PagedResponse<>(
                content,
                commentsPage.getNumber(),
                commentsPage.getSize(),
                commentsPage.getTotalElements(),
                commentsPage.getTotalPages(),
                commentsPage.isLast());
        
        return ResponseEntity.ok(response);
    }
    
    @PostMapping("/article/{articleId}")
    @PreAuthorize("hasRole('USER') or hasRole('ADMIN')")
    public ResponseEntity<?> addComment(
            @PathVariable Long articleId,
            @Valid @RequestBody CommentDto commentDto) {
        
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        UserDetailsImpl userDetails = (UserDetailsImpl) authentication.getPrincipal();
        
        User user = userRepository.findById(userDetails.getId())
                .orElseThrow(() -> new RuntimeException("错误：用户未找到。"));
        
        Article article = articleRepository.findById(articleId)
                .orElseThrow(() -> new RuntimeException("错误：文章未找到。"));
        
        Comment comment = new Comment();
        comment.setContent(commentDto.getContent());
        comment.setUser(user);
        comment.setArticle(article);
        
        if (commentDto.getParentId() != null) {
            Comment parentComment = commentRepository.findById(commentDto.getParentId())
                    .orElseThrow(() -> new RuntimeException("错误：父评论未找到。"));
            comment.setParent(parentComment);
        }
        
        commentRepository.save(comment);
        
        return ResponseEntity.ok(new MessageResponse("评论发布成功!"));
    }
    
    @PutMapping("/{id}")
    @PreAuthorize("hasRole('USER') or hasRole('ADMIN')")
    public ResponseEntity<?> updateComment(
            @PathVariable Long id,
            @Valid @RequestBody CommentDto commentDto) {
        
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        UserDetailsImpl userDetails = (UserDetailsImpl) authentication.getPrincipal();
        
        Comment comment = commentRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("错误：评论未找到。"));
        
        // 只有评论作者或管理员可以更新评论
        if (!comment.getUser().getId().equals(userDetails.getId()) && 
                !authentication.getAuthorities().stream().anyMatch(a -> a.getAuthority().equals("ROLE_ADMIN"))) {
            return ResponseEntity.badRequest().body(new MessageResponse("错误：没有权限更新此评论!"));
        }
        
        comment.setContent(commentDto.getContent());
        commentRepository.save(comment);
        
        return ResponseEntity.ok(new MessageResponse("评论更新成功!"));
    }
    
    @DeleteMapping("/{id}")
    @PreAuthorize("hasRole('USER') or hasRole('ADMIN')")
    public ResponseEntity<?> deleteComment(@PathVariable Long id) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        UserDetailsImpl userDetails = (UserDetailsImpl) authentication.getPrincipal();
        
        Comment comment = commentRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("错误：评论未找到。"));
        
        // 只有评论作者或管理员可以删除评论
        if (!comment.getUser().getId().equals(userDetails.getId()) && 
                !authentication.getAuthorities().stream().anyMatch(a -> a.getAuthority().equals("ROLE_ADMIN"))) {
            return ResponseEntity.badRequest().body(new MessageResponse("错误：没有权限删除此评论!"));
        }
        
        commentRepository.delete(comment);
        
        return ResponseEntity.ok(new MessageResponse("评论删除成功!"));
    }
    
    @PostMapping("/{id}/like")
    @PreAuthorize("hasRole('USER') or hasRole('ADMIN')")
    public ResponseEntity<?> likeComment(@PathVariable Long id) {
        Comment comment = commentRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("错误：评论未找到。"));
        
        comment.setLikes(comment.getLikes() + 1);
        commentRepository.save(comment);
        
        return ResponseEntity.ok(new MessageResponse("评论点赞成功!"));
    }
    
    @PostMapping("/{id}/dislike")
    @PreAuthorize("hasRole('USER') or hasRole('ADMIN')")
    public ResponseEntity<?> dislikeComment(@PathVariable Long id) {
        Comment comment = commentRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("错误：评论未找到。"));
        
        comment.setDislikes(comment.getDislikes() + 1);
        commentRepository.save(comment);
        
        return ResponseEntity.ok(new MessageResponse("评论点踩成功!"));
    }
    
    @GetMapping("/user/{userId}")
    public ResponseEntity<?> getCommentsByUser(
            @PathVariable Long userId,
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "10") int size) {
        
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new RuntimeException("错误：用户未找到。"));
        
        Pageable pageable = PageRequest.of(page, size, Sort.by(Sort.Direction.DESC, "createdAt"));
        Page<Comment> commentsPage = commentRepository.findByUser(user, pageable);
        
        List<CommentDto> content = commentsPage.getContent().stream()
                .map(this::convertToDto)
                .collect(Collectors.toList());
        
        PagedResponse<CommentDto> response = new PagedResponse<>(
                content,
                commentsPage.getNumber(),
                commentsPage.getSize(),
                commentsPage.getTotalElements(),
                commentsPage.getTotalPages(),
                commentsPage.isLast());
        
        return ResponseEntity.ok(response);
    }
    
    private CommentDto convertToDto(Comment comment) {
        CommentDto commentDto = new CommentDto();
        commentDto.setId(comment.getId());
        commentDto.setContent(comment.getContent());
        commentDto.setArticleId(comment.getArticle().getId());
        commentDto.setLikes(comment.getLikes());
        commentDto.setDislikes(comment.getDislikes());
        commentDto.setCreatedAt(comment.getCreatedAt());
        commentDto.setUpdatedAt(comment.getUpdatedAt());
        
        if (comment.getParent() != null) {
            commentDto.setParentId(comment.getParent().getId());
        }
        
        // 设置用户信息
        UserSummaryDto userDto = new UserSummaryDto();
        userDto.setId(comment.getUser().getId());
        userDto.setUsername(comment.getUser().getUsername());
        userDto.setAvatar(comment.getUser().getAvatar());
        userDto.setBio(comment.getUser().getBio());
        commentDto.setUser(userDto);
        
        // 获取回复
        List<Comment> replies = commentRepository.findByParent(comment);
        if (replies != null && !replies.isEmpty()) {
            List<CommentDto> replyDtos = new ArrayList<>();
            for (Comment reply : replies) {
                replyDtos.add(convertToDto(reply));
            }
            commentDto.setReplies(replyDtos);
        }
        
        return commentDto;
    }
} 